package com.cosin.model.po;

import com.cosin.model.XMLObject.RelationXMLO;
import com.cosin.model.dto.RelationDTO;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
import org.springframework.data.neo4j.core.schema.TargetNode;
import org.springframework.beans.BeanUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Data
@NoArgsConstructor
@RelationshipProperties
@Accessors(chain = true)
public class RelationPO {
    @Id
    @GeneratedValue
    private Long id;

    private Long relationId;
    private String name;
    private Long source;
    private Long target;
    private int width;
    private int projectId;
    private String propertiesAsString;
    private String properties;

    @JsonBackReference
    @TargetNode
    private NodePO targetNode;

    public RelationPO(RelationDTO relationDTO) {
        if (relationDTO != null) {
            BeanUtils.copyProperties(relationDTO, this);
            if (relationDTO.getProperties() != null) {
                setProperties(relationDTO.getProperties());
            }
        }
    }

    public RelationPO(RelationXMLO relationXMLO) {
        if (relationXMLO != null) {
            BeanUtils.copyProperties(relationXMLO, this);
            if (relationXMLO.getProperties() != null) {
                setProperties(relationXMLO.getProperties());
            }
        }
    }

    // 获取 properties 的 Map 形式
    public Map<String, String> getProperties() {
        if (propertiesAsString == null) {
            return new HashMap<>();
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(propertiesAsString, Map.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return new HashMap<>();
        }
    }

    // 设置 properties，同时更新 propertiesAsString
    public void setProperties(Map<String, String> properties) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            this.propertiesAsString = objectMapper.writeValueAsString(properties);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            this.propertiesAsString = null;
        }
    }
    @Override
    public String toString() {
        return "RelationPO{" +
                "id=" + id +
                ", relationId=" + relationId +
                ", name='" + name + '\'' +
                ", source=" + source +
                ", target=" + target +
                ", width=" + width +
                ", projectId=" + projectId +
                ", propertiesAsString='" + propertiesAsString + '\'' +
                ", targetNodeId=" + (targetNode != null ? targetNode.getId() : null) +
                '}';
    }
    @Override
    public int hashCode() {
        return Objects.hash(id, relationId, name, source, target, width, projectId, propertiesAsString);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        RelationPO relationPO = (RelationPO) obj;
        return Objects.equals(id, relationPO.id) &&
                Objects.equals(relationId, relationPO.relationId) &&
                Objects.equals(name, relationPO.name) &&
                Objects.equals(source, relationPO.source) &&
                Objects.equals(target, relationPO.target) &&
                Objects.equals(width, relationPO.width) &&
                Objects.equals(projectId, relationPO.projectId) &&
                Objects.equals(propertiesAsString, relationPO.propertiesAsString);
    }
}